WebSocket instead of HTTP-endpoint

Most modern web applications use WebSockets, when real-time data from servers need to be pushed out to the web applications, within a browser.

The implementation of the BACnet/WS in the DINGO-Stack, contains a HTTP-endpoint, that will proxy incoming HTTP-requests over on a open WebSocket-connection.

To use this option, the user has to follow these steps:

  1. Create a subscription as described earlier, but modify the callback: "callback": "http://192.168.1.110/bacnetws/cov-http-to-ws-proxy" where the IP address in the example is the address of the DINGO device that is hosting the BACnet web-services.
  2. Get the identifier (e.g. 1) provided for the created subscription, by parsing the HTTP-reply.
  3. Use the identifier (e.g. 1) and create a WebSocket connection to ws://192.168.1.110/bacnetws/cov-http-to-ws-proxy/1?alt=json where the IP address in the example is the address of the DINGO device that is hosting the BACnet web-services.

Study the following JavaScript functions to see how the subscription and WebSocket connection is made .

function CreateSubscribtion(device,object) {

    // device could for example be: 1000

    // object could for example be: analog-input,18

    var xmlHttp = new XMLHttpRequest();

    xmlHttp.onreadystatechange = function () {

        if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {

            // SUBSCRIPTION CREATED

            var headerString = xmlHttp.getResponseHeader("Location");

            if (headerString != null) {

                var urlParts = headerString.split("/");

                subscribtionID = urlParts[urlParts.length - 1];

                WebSocketSubscribe(urlParts[urlParts.length - 1]);

            }

        }

    }

    // CREATE BACnet/WS SUBSCRIPTION

    var host = "192.168.1.110";

    xmlHttp.open("POST", "http://" + host + "/bacnetws/.subs?alt=json", true); // true for asynchronous

    var subscription = {

        label: "My subscription",

        callback: "http://" + host + "/bacnetws/cov-http-to-ws-proxy",

        lifetime: "120",

        covs: {

            1: {

                path: "/.bacnet/.local/" + device + "/" + object,

                increment: "1"

            }

        }

    };

    xmlHttp.send(JSON.stringify(subscription));

}

 

function WebSocketSubscribe(id) {

    var host = "192.168.1.110";

    var wslocation = "ws://" + host + "/bacnetws/cov-http-to-ws-proxy/" + id + "?alt=json";

    if ("WebSocket" in window) {

        // CONNECTING TO WEBSOCKET

        ws = new WebSocket(wslocation);

        ws.onopen = function (event) {

            // CONNECTED

        };

        ws.onmessage = function (evt) {

            // RECIEVED DATA

            var msg = evt.data.toString();

            // Chrome and Firefox could not parse JSON to object,

            // not until we replace control characters out of the string.

            msg = msg.replace(/[\x00-\x1F\x7F-\x9F]/g, "");

            try {

                var obj = JSON.parse(msg);

                alert(obj["1"].$value);

            }

            catch (e) {

                alert(msg);

            }

        };

        ws.onclose = function () {

            // CONNECTION CLOSED

        };

        ws.onerror = function (error) {

            alert("ERROR: " + error.data);

        };

    }

    else {

        alert("This browser does not support WebSockets.");

    }

}

A web application (testclient.htm) exists on the file system, that uses WebSockets and can be studied furthered.